/// <summary>
/// Copyright 2010 Ivo Limmen (ivo@limmen.org)
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
/// 
/// http://www.apache.org/licenses/LICENSE-2.0
/// 
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// </summary>

using System;
using System.Xml;
using System.Xml.XPath;
using System.IO;
using Services.Configuration.Api;
using System.Diagnostics;
using Model = Services.Configuration.Model;

namespace Services.Configuration	
{
	public class ConfigurationReader
	{
		private XmlDocument document;
				
		public ConfigurationReader(IConfigurationLoader loader)
		{
			this.document = loader.Load();
			
			if (this.document == null || this.document.ChildNodes.Count == 0) 
			{
				throw new Exception("No configuration file could be read!");
			}
		}

		public IResolver Read() 
		{
			Model.Configuration configuration = new Model.Configuration();

			int index = 0;
			XmlNode configurationNode = this.document.ChildNodes.Item(index++);

			while (!configurationNode.LocalName.Equals("configuration"))
			{
				configurationNode = this.document.ChildNodes.Item(index++);
			}

			foreach(XmlNode node in configurationNode.ChildNodes) 
			{
				if (node.LocalName.Equals("documentation")) 
				{
					configuration.SetDocumentation(ReadDocumentation(node));
				}
				else
				{					
					configuration.AddSection(ReadSection(node));
				}
			}
			
			return new VariableSettingResolver(configuration);
		}
		
		private Model.Section ReadSection(XmlNode sectionNode) 
		{	
			string name = GetAttributeValue(sectionNode, "name");
			string host = GetAttributeValue(sectionNode, "host");

			Model.Section section = new Model.Section(name, host);
						
			foreach(XmlNode node in sectionNode.ChildNodes) 
			{
				if (node.LocalName.Equals("documentation")) 
				{
					section.SetDocumentation(ReadDocumentation(node));
				}
				else 
				{				
					section.AddKey(ReadKey(node));
				}
			}
			
			return section;
		}

		private Model.Meta.Documentation ReadDocumentation(XmlNode docNode)
		{
			string value = docNode.InnerText;
			
			return new Model.Meta.Documentation(value);
		}
		
		private Model.Key ReadKey(XmlNode keyNode)
		{
			string name = GetAttributeValue(keyNode, "name");
			string description = GetAttributeValue(keyNode, "description");
			string value = keyNode.InnerText;
			
			return new Model.Key(name, value, description);
		}
		
		private string GetAttributeValue(XmlNode node, string attributeName)
		{
			XmlAttribute attribute = node.Attributes[attributeName];
			
			if (attribute != null) 
			{
				return attribute.Value;
			}
			
			return null;
		}
	}
}
